/* eslint-disable @typescript-eslint/no-explicit-any */
import { Signal, signal } from '@preact/signals';
import { ChatMessage } from '../../entity';
import { IChatMessage, IChatOptions } from '../../interface';
import { createUUID, IndexedDBUtil } from '../../utils';
import { TextUtil } from '../../utils/util/util';
import { AIChatConst } from '../../constants';

/**
 * 聊天逻辑控制器
 *
 * @author chitanda
 * @date 2023-10-09 15:10:51
 * @export
 * @class AiChatController
 */
export class AiChatController {
  /**
   * 聊天记录
   *
   * @author chitanda
   * @date 2023-10-16 16:10:29
   * @type {Signal<ChatMessage[]>}
   */
  readonly messages: Signal<ChatMessage[]> = signal([]);

  /**
   * 聊天框输入值
   *
   * @author chitanda
   * @date 2023-10-16 15:10:43
   * @type {Signal<string>}
   */
  readonly input: Signal<string> = signal('');

  /**
   * 视图参数
   *
   * @author tony001
   * @date 2025-02-24 14:02:23
   * @type {object}
   */
  readonly context: object;

  /**
   * 视图参数
   *
   * @author tony001
   * @date 2025-02-24 14:02:32
   * @type {object}
   */
  readonly params: object;

  /**
   * 应用实体标记
   *
   * @author tony001
   * @date 2025-02-24 14:02:10
   * @type {string}
   */
  readonly appDataEntityId: string;

  /**
   * 话题标识
   *
   * @author tony001
   * @date 2025-02-24 18:02:02
   * @type {(string | undefined)}
   */
  readonly topicId: string | undefined = undefined;

  /**
   * Creates an instance of AiChatController.
   *
   * @author chitanda
   * @date 2023-10-15 19:10:34
   * @param {IChatOptions} opts 聊天配置
   */
  constructor(readonly opts: IChatOptions) {
    this.context = opts.context;
    this.params = opts.params;
    this.appDataEntityId = opts.appDataEntityId;
    this.topicId = opts.topicId;
    this.fecthHistory();
  }

  /**
   * 获取历史记录
   *
   * @author tony001
   * @date 2025-02-24 13:02:52
   * @return {*}  {Promise<boolean>}
   */
  async fecthHistory(): Promise<boolean> {
    if (this.topicId) {
      const result: any = await IndexedDBUtil.getData(
        AIChatConst.DATA_BASE_NAME,
        AIChatConst.DATA_TABLE_NAME,
        this.topicId,
      );
      if (result && result.data && result.data.length > 0) {
        result.data.forEach((item: { role: any; content: any }) => {
          const msg = {
            messageid: createUUID(),
            state: 30,
            type: 'DEFAULT',
            role: item.role,
            content: item.content,
          } as const;
          this.addMessage(msg);
        });
        return true;
      }
    }
    return this.opts.history(this.context, this.params, {
      appDataEntityId: this.appDataEntityId,
    });
  }

  /**
   * 更新数据到indexdb
   *
   * @author tony001
   * @date 2025-02-24 18:02:41
   * @return {*}  {Promise<void>}
   */
  async asyncToIndexDB(action: 'ADD' | 'UPDATE'): Promise<void> {
    if (!this.topicId) {
      return;
    }
    const data = {
      id: this.topicId,
      data: this.messages.value.map(item => item._origin),
      timestamp: new Date().getTime(),
    };
    const dbAction = action === 'ADD' ? 'addData' : 'updateData';
    await IndexedDBUtil[dbAction](
      AIChatConst.DATA_BASE_NAME,
      AIChatConst.DATA_TABLE_NAME,
      data,
    );
  }

  /**
   * 设置聊天框值
   *
   * @author chitanda
   * @date 2023-10-16 16:10:21
   * @param {string} input
   */
  setInput(input: string): void {
    this.input.value = input || '';
  }

  /**
   * 新增聊天记录
   *
   * @author chitanda
   * @date 2023-10-09 15:10:15
   * @param {IMessage} data
   */
  addMessage(data: IChatMessage): void {
    const chatMsg = this.messages.value.find(
      item => item.messageid === data.messageid,
    );
    if (chatMsg) {
      chatMsg.update(data);
      this.messages.value = [...this.messages.value];
    } else {
      this.messages.value = [...this.messages.value, new ChatMessage(data)];
    }
    this.asyncToIndexDB('ADD');
  }

  /**
   * 替换已经存在的聊天消息
   *
   * @author chitanda
   * @date 2023-10-16 22:10:49
   * @param {IChatMessage} data
   */
  replaceMessage(data: IChatMessage): void {
    const i = this.messages.value.findIndex(
      item => item.messageid === data.messageid,
    );
    if (i !== -1) {
      this.messages.value[i] = new ChatMessage(data);
      this.messages.value = [...this.messages.value];
    } else {
      this.messages.value = [...this.messages.value, new ChatMessage(data)];
    }
    this.asyncToIndexDB('UPDATE');
  }

  /**
   * 提问
   *
   * @author chitanda
   * @date 2023-10-09 20:10:43
   * @return {*}  {Promise<void>}
   */
  async question(input: string): Promise<void> {
    this.addMessage({
      state: 30,
      messageid: createUUID(),
      role: 'USER',
      type: 'DEFAULT',
      content: input,
    });
    await this.opts.question(
      this.context,
      this.params,
      { appDataEntityId: this.appDataEntityId },
      this.messages.value
        .filter(item => item.type !== 'ERROR')
        .map(item => item._origin),
    );
    if (this.opts.action) {
      this.opts.action('question', input);
    }
  }

  /**
   * 回填选中的消息
   *
   * @author chitanda
   * @date 2023-10-16 18:10:19
   * @param {IChatMessage} message
   */
  backfill(message: IChatMessage): void {
    if (this.opts.action) {
      this.opts.action('backfill', message);
    }
  }

  /**
   *
   * 删除指定消息，如果是用户提问的刷新调用的删除，则需要删除从问题开始到最后的所有记录
   * @param {IChatMessage} message
   * @param {boolean} [isuser=false]
   * @memberof AiChatController
   */
  deleteMessage(message: IChatMessage): void {
    const i = this.messages.value.findIndex(
      item => item.messageid === message.messageid,
    );
    if (i !== -1) {
      this.messages.value.splice(i, 1);
      this.messages.value = [...this.messages.value];
    }
    this.asyncToIndexDB('UPDATE');
    if (this.opts.action) {
      this.opts.action('deletemsg', message);
    }
  }

  /**
   * 刷新当前消息
   *
   * @memberof AiChatController
   */
  async refreshMessage(message: IChatMessage, isuser: boolean = false) {
    const i = this.messages.value.findIndex(
      item => item.messageid === message.messageid,
    );

    if (isuser) {
      this.messages.value.splice(i + 1, this.messages.value.length - i - 1);
      this.messages.value = [...this.messages.value];
      await this.opts.question(
        this.context,
        this.params,
        { appDataEntityId: this.appDataEntityId },
        this.messages.value
          .filter(item => item.type !== 'ERROR')
          .map(item => item._origin),
      );
    } else if (i === this.messages.value.length - 1) {
      this.messages.value.pop();
      this.messages.value = [...this.messages.value];
      await this.opts.question(
        this.context,
        this.params,
        { appDataEntityId: this.appDataEntityId },
        this.messages.value
          .filter(item => item.type !== 'ERROR')
          .map(item => item._origin),
      );
    } else {
      const lastques = this.messages.value[i - 1].content;
      this.messages.value.splice(i - 1, 2);
      this.question(lastques);
    }
    this.asyncToIndexDB('UPDATE');
    if (this.opts.action) {
      this.opts.action('refreshmsg', message);
    }
  }

  /**
   * 复制消息
   *
   * @param {IChatMessage} message
   * @memberof AiChatController
   */
  copyMessage(message: IChatMessage) {
    const text = message.content;
    TextUtil.copy(text);
    if (this.opts.action) {
      this.opts.action('copymsg', message);
    }
  }
}
